package com.ukefu.webim.service.es;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder.Operator;
import org.elasticsearch.index.query.support.QueryInnerHitBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Repository;

import com.ukefu.webim.service.repository.UKAggResultExtractor;
import com.ukefu.webim.service.repository.UKResultMapper;
import com.ukefu.webim.service.repository.UserRepository;
import com.ukefu.webim.util.WorkOrdersDataProcesser;
import com.ukefu.webim.util.WorkOrdersUtils;
import com.ukefu.webim.web.model.WorkOrders;

@Repository
public class WorkOrdersRepositoryImpl implements WorkOrdersEsCommonRepository{
	@Autowired
	private UserRepository userRes ;
	
	@Autowired
	private ContactsRepository contactsRes ;
	
	private ElasticsearchTemplate elasticsearchTemplate;

	@Autowired
	public void setElasticsearchTemplate(ElasticsearchTemplate elasticsearchTemplate) {
		this.elasticsearchTemplate = elasticsearchTemplate;
    }

	@Override
	public Page<WorkOrders> findByCreater(BoolQueryBuilder boolQueryBuilder, boolean haschild , boolean includeDeleteData ,String q ,String creater , Pageable page) {
		
		if(!StringUtils.isBlank(creater)){
			if(haschild){
				boolQueryBuilder.must(QueryBuilders.hasChildQuery("uk_favorites",QueryBuilders.boolQuery().must( QueryBuilders.termQuery("creater", creater)).must( QueryBuilders.termQuery("code", "true"))).innerHit(new QueryInnerHitBuilder())) ;
			}else{
				boolQueryBuilder.should(QueryBuilders.hasChildQuery("uk_favorites",QueryBuilders.boolQuery().must( QueryBuilders.termQuery("creater", creater)).must( QueryBuilders.termQuery("code", "true"))).innerHit(new QueryInnerHitBuilder())) ;
			}
		}
		if(includeDeleteData){
			boolQueryBuilder.must(QueryBuilders.termQuery("datastatus" , true)) ;
		}else{
			boolQueryBuilder.must(QueryBuilders.termQuery("datastatus" , false)) ;
		}
		if(!StringUtils.isBlank(q)){
	    	boolQueryBuilder.must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
	    }
		return processQuery(boolQueryBuilder , page);
	}
	
	private Page<WorkOrders> processQuery(BoolQueryBuilder boolQueryBuilder, Pageable page){
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder).withSort(new FieldSortBuilder("updatetime").unmappedType("date").order(SortOrder.DESC)).withSort(new FieldSortBuilder("name").unmappedType("string").order(SortOrder.DESC));
		
		searchQueryBuilder.withPageable(page) ;
		searchQueryBuilder.withHighlightFields(new HighlightBuilder.Field("title").fragmentSize(200)) ;
		
		Page<WorkOrders> workOrdersList = null ;
		if(elasticsearchTemplate.indexExists(WorkOrders.class)){
			workOrdersList = elasticsearchTemplate.queryForPage(searchQueryBuilder.build() , WorkOrders.class , new UKResultMapper(new WorkOrdersDataProcesser())) ;
		}
		if(workOrdersList.getContent().size() > 0){
			WorkOrdersUtils.processWorkOrders(workOrdersList.getContent() , userRes , contactsRes) ;
			
		}
		return workOrdersList;
	}
	@Override
	public Page<WorkOrders> countById(
			BoolQueryBuilder boolQueryBuilder, String field , boolean includeDeleteData , String q, int p, int ps, Pageable page) {
		Page<WorkOrders> pages  = null ;
		if(includeDeleteData){
			boolQueryBuilder.must(QueryBuilders.termQuery("datastatus" , true)) ;
		}else{
			boolQueryBuilder.must(QueryBuilders.termQuery("datastatus" , false)) ;
		}
		if(!StringUtils.isBlank(q)){
	    	boolQueryBuilder.must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
	    }
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder) ;
		
		if(!StringUtils.isBlank(field)){
			searchQueryBuilder.addAggregation(AggregationBuilders.terms(field).field(field)) ;
		}
		
		if(!StringUtils.isBlank(q)){
		   	searchQueryBuilder.withQuery(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
		}
    	SearchQuery searchQuery = searchQueryBuilder.build().setPageable(new PageRequest(p, ps));
	    if(elasticsearchTemplate.indexExists(WorkOrders.class)){
	    	pages = elasticsearchTemplate.queryForPage(searchQuery, WorkOrders.class  , new UKAggResultExtractor(field) );
	    }
	    return pages ; 
	}

	@Override
	public List<WorkOrders> findByContactsAndOrgi(String contactsid , String creater, String orgi) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		BoolQueryBuilder bq = QueryBuilders.boolQuery() ; 
		bq.should(QueryBuilders.termQuery("cusid", contactsid)) ;
		bq.should(QueryBuilders.termQuery("dataid", contactsid)) ;
		boolQueryBuilder.must(QueryBuilders.termQuery("datastatus", false)) ;
		boolQueryBuilder.must(bq); 
		if(!StringUtils.isBlank(creater)){
			boolQueryBuilder.should(QueryBuilders.hasChildQuery("uk_favorites",QueryBuilders.boolQuery().must( QueryBuilders.termQuery("creater", creater)).must( QueryBuilders.termQuery("code", "true"))).innerHit(new QueryInnerHitBuilder())) ;
		}
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder) ;
		searchQueryBuilder.withPageable(new PageRequest(0, Integer.SIZE * 10)).withSort(new FieldSortBuilder("createtime").unmappedType("date").order(SortOrder.DESC)).withSort(new FieldSortBuilder("name").unmappedType("string").order(SortOrder.DESC)) ;
		Page<WorkOrders> workOrdersList = null ;
		if(elasticsearchTemplate.indexExists(WorkOrders.class)){
			workOrdersList = elasticsearchTemplate.queryForPage(searchQueryBuilder.build() , WorkOrders.class , new UKResultMapper(new WorkOrdersDataProcesser())) ;
	    }
		if(workOrdersList.getContent().size() > 0){
			WorkOrdersUtils.processWorkOrders(workOrdersList.getContent(), userRes , contactsRes) ;
			
		}
		return workOrdersList.getContent();
	}

	@Override
	public Page<WorkOrders> findById(BoolQueryBuilder boolQueryBuilder, boolean datastatus, String orgi, Pageable page) {
		boolQueryBuilder.must(QueryBuilders.termQuery("orgi" , orgi)) ;
		if(datastatus){
			boolQueryBuilder.must(QueryBuilders.termQuery("datastatus" , true)) ;
		}else{
			boolQueryBuilder.must(QueryBuilders.termQuery("datastatus" , false)) ;
		}
		return processQuery(boolQueryBuilder , page);
	}

	@Override
	public WorkOrders findByIdAndOrgi(String id, String orgi) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		BoolQueryBuilder bq = QueryBuilders.boolQuery() ; 
		bq.must(QueryBuilders.termQuery("id", id)) ;
		bq.must(QueryBuilders.termQuery("orgi", orgi)) ;
		boolQueryBuilder.must(QueryBuilders.termQuery("datastatus", false)) ;
		boolQueryBuilder.must(bq); 
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder) ;
		searchQueryBuilder.withPageable(new PageRequest(0, Integer.SIZE * 10)).withSort(new FieldSortBuilder("createtime").unmappedType("date").order(SortOrder.DESC)).withSort(new FieldSortBuilder("name").unmappedType("string").order(SortOrder.DESC)) ;
		Page<WorkOrders> workOrdersList = null ;
		if(elasticsearchTemplate.indexExists(WorkOrders.class)){
			workOrdersList = elasticsearchTemplate.queryForPage(searchQueryBuilder.build() , WorkOrders.class , new UKResultMapper(new WorkOrdersDataProcesser())) ;
	    }
		if(workOrdersList.getContent().size() > 0){
			WorkOrdersUtils.processWorkOrders(workOrdersList.getContent(), userRes , contactsRes) ;
			return workOrdersList.getContent().get(0);
		}else {
			return null;
		}
	}

	@Override
	public List<WorkOrders> findByTemplateidAndQualitystatus(String templateid,
			String qualitystatus) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		BoolQueryBuilder bq = QueryBuilders.boolQuery() ; 
		bq.must(QueryBuilders.termQuery("templateid", templateid)) ;
		bq.must(QueryBuilders.termQuery("qualitystatus", qualitystatus)) ;
		boolQueryBuilder.must(QueryBuilders.termQuery("datastatus", false)) ;
		boolQueryBuilder.must(bq); 
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder) ;
		searchQueryBuilder.withPageable(new PageRequest(0, Integer.SIZE * 10)).withSort(new FieldSortBuilder("createtime").unmappedType("date").order(SortOrder.DESC)).withSort(new FieldSortBuilder("name").unmappedType("string").order(SortOrder.DESC)) ;
		Page<WorkOrders> workOrdersList = null ;
		if(elasticsearchTemplate.indexExists(WorkOrders.class)){
			workOrdersList = elasticsearchTemplate.queryForPage(searchQueryBuilder.build() , WorkOrders.class , new UKResultMapper(new WorkOrdersDataProcesser())) ;
	    }
		if(workOrdersList.getContent().size() > 0){
			WorkOrdersUtils.processWorkOrders(workOrdersList.getContent(), userRes , contactsRes) ;
			
		}
		return workOrdersList.getContent();
	}

	@Override
	public List<WorkOrders> findByOrgiAndQualitydistypeAndQualitydisuser(String orgi, String qualitydistype,
			String qualitydisuser) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(QueryBuilders.termQuery("qualitydisuser", qualitydisuser) );
		boolQueryBuilder.must(QueryBuilders.termQuery("orgi", orgi) );
		boolQueryBuilder.must(QueryBuilders.termQuery("qualitydistype", qualitydistype) );
		return this.proccessQuery(boolQueryBuilder);
	}
	public List<WorkOrders> proccessQuery(BoolQueryBuilder boolQueryBuilder){
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder) ;
		searchQueryBuilder.withPageable(new PageRequest(0, 10000));
		Page<WorkOrders> WorkOrdersList = null ;
		if(elasticsearchTemplate.indexExists(WorkOrders.class)){
			WorkOrdersList = elasticsearchTemplate.queryForPage(searchQueryBuilder.build() , WorkOrders.class ) ;
	    }
		return WorkOrdersList.getContent();
	}

	@Override
	public List<WorkOrders> findByOrgiAndQualitydisorgan(BoolQueryBuilder boolQueryBuilder) {
		
		return this.proccessQuery(boolQueryBuilder);
	}
	
	@Override
	public Page<WorkOrders> findByOrgi(BoolQueryBuilder boolQueryBuilder, Pageable page) {
		return this.processQuery(boolQueryBuilder, page);
	}

	@Override
	public WorkOrders getByIdAndOrgi(String id, String orgi) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		BoolQueryBuilder bq = QueryBuilders.boolQuery() ; 
		bq.must(QueryBuilders.termQuery("id", id)) ;
		bq.must(QueryBuilders.termQuery("orgi", orgi)) ;
		boolQueryBuilder.must(QueryBuilders.termQuery("datastatus", false)) ;
		boolQueryBuilder.must(bq); 
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder) ;
		searchQueryBuilder.withPageable(new PageRequest(0, Integer.SIZE * 10)).withSort(new FieldSortBuilder("createtime").unmappedType("date").order(SortOrder.DESC)).withSort(new FieldSortBuilder("name").unmappedType("string").order(SortOrder.DESC)) ;
		Page<WorkOrders> workOrdersList = null ;
		if(elasticsearchTemplate.indexExists(WorkOrders.class)){
			workOrdersList = elasticsearchTemplate.queryForPage(searchQueryBuilder.build() , WorkOrders.class , new UKResultMapper(new WorkOrdersDataProcesser())) ;
	    }
		if(workOrdersList.getContent().size() > 0){
			WorkOrdersUtils.processWorkOrders(workOrdersList.getContent(), userRes , contactsRes) ;
			return workOrdersList.getContent().get(0);
		}else {
			return null;
		}
	}

	@Override
	public List<WorkOrders> findByIdInAndOrgi(List<String> ids, String orgi) {
		List<WorkOrders> workOrderList = null;
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		BoolQueryBuilder bq = QueryBuilders.boolQuery() ; 
		if (ids != null && ids.size() > 0) {
			for(String id : ids) {
				if (!StringUtils.isBlank(id)) {
					bq.should(QueryBuilders.termQuery("id", id)) ;
				}
			}
		}
		boolQueryBuilder.must(bq); 
		boolQueryBuilder.must(QueryBuilders.termQuery("datastatus", false)) ;
		boolQueryBuilder.must(QueryBuilders.termQuery("orgi", orgi)) ;
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder) ;
		searchQueryBuilder.withPageable(new PageRequest(0, 10000)).withSort(new FieldSortBuilder("createtime").unmappedType("date").order(SortOrder.DESC)).withSort(new FieldSortBuilder("name").unmappedType("string").order(SortOrder.DESC)) ;
		Page<WorkOrders> workOrdersList = null ;
		if(elasticsearchTemplate.indexExists(WorkOrders.class)){
			workOrdersList = elasticsearchTemplate.queryForPage(searchQueryBuilder.build() , WorkOrders.class , new UKResultMapper(new WorkOrdersDataProcesser())) ;
		}
		if(workOrdersList.getContent().size() > 0){
			WorkOrdersUtils.processWorkOrders(workOrdersList.getContent(), userRes , contactsRes) ;
			workOrderList = workOrdersList.getContent();
		}
		return workOrderList;
	}

	@Override
	public List<WorkOrders> findByCusidAndOrgi(String cusid, String orgi) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(QueryBuilders.termQuery("cusid", cusid) );
		boolQueryBuilder.must(QueryBuilders.termQuery("orgi", orgi) );
		return this.proccessQuery(boolQueryBuilder);
	}
}
